package com.hm.oltu.api;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.hm.common.util.CommonUtil;
import com.hm.oltu.def.OauthDef;
import com.hm.oltu.service.OAuthService;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 2016年12月5日 下午6:15:23
 * @version 1.0
 * @describe
 */
@Slf4j
@RestController
public class AccessTokenController {

	@Autowired
	private OAuthService oAuthService;

	@RequestMapping(value = "/accessToken", method = RequestMethod.POST)
	public Object token(HttpServletRequest request) {
		try {
			// 构建OAuth请求
			OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);
			// 检查提交的客户端id是否正确
			if (CommonUtil.isEmpty(oauthRequest.getClientId())
					|| !oAuthService.checkClientId(oauthRequest.getClientId())) {
				return error(HttpServletResponse.SC_BAD_REQUEST, OAuthError.TokenResponse.INVALID_CLIENT,
						OauthDef.INVALID_CLIENT_ID);
			}

			// 检查客户端安全KEY是否正确
			if (CommonUtil.isEmpty(oauthRequest.getClientSecret())
					|| !oAuthService.checkClientSecret(oauthRequest.getClientSecret())) {
				return error(HttpServletResponse.SC_BAD_REQUEST, OAuthError.TokenResponse.UNAUTHORIZED_CLIENT,
						OauthDef.INVALID_CLIENT_ID);
			}

			String authCode = oauthRequest.getParam(OAuth.OAUTH_CODE);
			// 检查验证类型，此处只检查AUTHORIZATION_CODE类型，其他的还有PASSWORD或REFRESH_TOKEN
			if (oauthRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals(GrantType.AUTHORIZATION_CODE.toString())) {
				if (!oAuthService.checkAuthCode(authCode)) {
					return error(HttpServletResponse.SC_BAD_REQUEST, OAuthError.TokenResponse.INVALID_GRANT,
							OauthDef.INVALID_AUTH_CODE);
				}
			}

			// 生成Access Token
			OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
			final String accessToken = oauthIssuerImpl.accessToken();
			oAuthService.addAccessToken(accessToken, oAuthService.getUsernameByAuthCode(authCode));

			// 生成OAuth响应
			OAuthResponse response = OAuthASResponse.tokenResponse(HttpServletResponse.SC_OK)
					.setAccessToken(accessToken).setExpiresIn(String.valueOf(oAuthService.getExpireIn()))
					.buildJSONMessage();

			// 根据OAuthResponse生成ResponseEntity
			return new ResponseEntity<String>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));

		} catch (Exception e) {
			log.error("authorize other error $s ", e.getMessage());
			e.printStackTrace();
			return error(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), OauthDef.OTHER_ERROR);
		}
	}

	@RequestMapping(value = "/checkAccessToken", method = RequestMethod.POST)
	public ResponseEntity<Object> checkAccessToken(@RequestParam("accessToken") String accessToken) {
		return oAuthService.checkAccessToken(accessToken)
				? new ResponseEntity<Object>(HttpStatus.valueOf(HttpServletResponse.SC_OK))
				: new ResponseEntity<Object>(HttpStatus.valueOf(HttpServletResponse.SC_UNAUTHORIZED));
	}

	private ResponseEntity<String> error(int responseStatu, String error, String desc) {
		try {
			log.error("authorize error responseStatu=[$s],error=[$s] ,desc=[$s]", responseStatu, error, desc);
			OAuthResponse response = OAuthASResponse.errorResponse(responseStatu).setError(error)
					.setErrorDescription(desc).buildJSONMessage();
			return new ResponseEntity<String>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
		} catch (OAuthSystemException e) {
			log.error("authorize other error $s ", e.getMessage());
			return error(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), OauthDef.OTHER_ERROR);
		}
	}
}
